home *** CD-ROM | disk | FTP | other *** search
- /*
- * http_config.c: auxillary functions for reading httpd's config file
- * and converting filenames into a namespace
- *
- * Rob McCool
- *
- */
-
- #include "httpd.h"
-
-
- /* Server config globals */
- int standalone;
- int port;
- uid_t user_id;
- gid_t group_id;
- char server_root[MAX_STRING_LEN];
- char error_fname[MAX_STRING_LEN];
- char xfer_fname[MAX_STRING_LEN];
- char pid_fname[MAX_STRING_LEN];
- char server_admin[MAX_STRING_LEN];
- char *server_hostname;
- char srm_confname[MAX_STRING_LEN];
- char server_confname[MAX_STRING_LEN];
- char access_confname[MAX_STRING_LEN];
- char types_confname[MAX_STRING_LEN];
- int timeout;
-
- void process_server_config() {
- FILE *cfg;
- char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
- int n=0;
-
- standalone = 1;
- port = DEFAULT_PORT;
- #ifndef AMIGA
- user_id = uname2id(DEFAULT_USER);
- #else
- user_id = 0;
- #endif
- group_id = gname2id(DEFAULT_GROUP);
- /* ServerRoot set in httpd.c */
- make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
- make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
- make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
- strcpy(server_admin,DEFAULT_ADMIN);
- server_hostname = NULL;
- make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
- /* server_confname set in httpd.c */
- make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
- make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
-
- timeout = DEFAULT_TIMEOUT;
-
- if(!(cfg = fopen(server_confname,"r"))) {
- fprintf(stderr,"httpd: could not open server config. file %s\n",server_confname);
- perror("fopen");
- exit(1);
- }
- /* Parse server config file. Remind me to learn yacc. */
- while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
- ++n;
- if((l[0] != '#') && (l[0] != '\0')) {
- cfg_getword(w,l);
-
- if(!strcasecmp(w,"ServerType")) {
- if(!strcasecmp(l,"inetd")) standalone=0;
- else if(!strcasecmp(l,"standalone")) standalone=1;
- else {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
- fprintf(stderr,"ServerType is either inetd or standalone.\n");
- exit(1);
- }
- }
- else if(!strcasecmp(w,"Port")) {
- cfg_getword(w,l);
- port = atoi(w);
- }
- else if(!strcasecmp(w,"User")) {
- cfg_getword(w,l);
- #ifndef AMIGA
- user_id = uname2id(w);
- #else
- user_id = 0;
- #endif
- }
- else if(!strcasecmp(w,"Group")) {
- cfg_getword(w,l);
- group_id = gname2id(w);
- }
- else if(!strcasecmp(w,"ServerAdmin")) {
- cfg_getword(w,l);
- strcpy(server_admin,w);
- }
- else if(!strcasecmp(w,"ServerName")) {
- cfg_getword(w,l);
- server_hostname = strdup(w);
- }
- else if(!strcasecmp(w,"ServerRoot")) {
- cfg_getword(w,l);
- if(!is_directory(w)) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
- fprintf(stderr,"%s is not a valid directory.\n",w);
- exit(1);
- }
- strcpy(server_root,w);
- make_full_path(server_root,DEFAULT_ERRORLOG,error_fname);
- make_full_path(server_root,DEFAULT_XFERLOG,xfer_fname);
- make_full_path(server_root,DEFAULT_PIDLOG,pid_fname);
- make_full_path(server_root,RESOURCE_CONFIG_FILE,srm_confname);
- make_full_path(server_root,ACCESS_CONFIG_FILE,access_confname);
- make_full_path(server_root,TYPES_CONFIG_FILE,types_confname);
- }
- else if(!strcasecmp(w,"ErrorLog")) {
- cfg_getword(w,l);
- if(w[0] != '/')
- make_full_path(server_root,w,error_fname);
- else
- strcpy(error_fname,w);
- }
- else if(!strcasecmp(w,"TransferLog")) {
- cfg_getword(w,l);
- if(w[0] != '/')
- make_full_path(server_root,w,xfer_fname);
- else strcpy(xfer_fname,w);
- }
- else if(!strcasecmp(w,"PidFile")) {
- cfg_getword(w,l);
- if(w[0] != '/')
- make_full_path(server_root,w,pid_fname);
- else strcpy(pid_fname,w);
- }
- else if(!strcasecmp(w,"AccessConfig")) {
- cfg_getword(w,l);
- if(w[0] != '/')
- make_full_path(server_root,w,access_confname);
- else strcpy(access_confname,w);
- }
- else if(!strcasecmp(w,"ResourceConfig")) {
- cfg_getword(w,l);
- if(w[0] != '/')
- make_full_path(server_root,w,srm_confname);
- else strcpy(srm_confname,w);
- }
- else if(!strcasecmp(w,"TypesConfig")) {
- cfg_getword(w,l);
- if(w[0] != '/')
- make_full_path(server_root,w,types_confname);
- else strcpy(types_confname,w);
- }
- else if(!strcasecmp(w,"Timeout"))
- timeout = atoi(l);
- else {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,server_confname);
- fprintf(stderr,"Unknown keyword %s.\n",w);
- exit(1);
- }
- }
- }
- fclose(cfg);
- }
-
-
-
- /* Document config globals */
- char user_dir[MAX_STRING_LEN];
- char index_name[MAX_STRING_LEN];
- char access_name[MAX_STRING_LEN];
- char document_root[MAX_STRING_LEN];
- char default_type[MAX_STRING_LEN];
-
- void process_resource_config() {
- FILE *cfg;
- char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
- int n=0;
-
- strcpy(user_dir,DEFAULT_USER_DIR);
- strcpy(index_name,DEFAULT_INDEX);
- strcpy(access_name,DEFAULT_ACCESS_FNAME);
- strcpy(document_root,DOCUMENT_LOCATION);
- strcpy(default_type,DEFAULT_TYPE);
-
- if(!(cfg = fopen(srm_confname,"r"))) {
- fprintf(stderr,"httpd: could not open document config. file %s\n",
- srm_confname);
- perror("fopen");
- exit(1);
- }
-
- while(!(cfg_getline(l,MAX_STRING_LEN,cfg))) {
- ++n;
- if((l[0] != '#') && (l[0] != '\0')) {
- cfg_getword(w,l);
-
- if(!strcasecmp(w,"ScriptAlias")) {
- char w2[MAX_STRING_LEN];
-
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0')) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,
- srm_confname);
- fprintf(stderr,
- "ScriptAlias must be followed by a fakename, one space, then a realname.\n");
- exit(1);
- }
- add_alias(w,w2,SCRIPT_CGI);
- }
- if(!strcasecmp(w,"OldScriptAlias")) {
- char w2[MAX_STRING_LEN];
-
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0')) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,
- srm_confname);
- fprintf(stderr,
- "ScriptAlias must be followed by a fakename, one space, then a realname.\n");
- exit(1);
- }
- add_alias(w,w2,SCRIPT_NCSA);
- }
- else if(!strcasecmp(w,"UserDir")) {
- cfg_getword(w,l);
- if(!strcmp(w,"DISABLED"))
- user_dir[0] = '\0';
- else
- strcpy(user_dir,w);
- }
- else if(!strcasecmp(w,"DirectoryIndex")) {
- cfg_getword(w,l);
- strcpy(index_name,w);
- }
- else if(!strcasecmp(w,"DefaultType")) {
- cfg_getword(w,l);
- strcpy(default_type,w);
- }
- else if(!strcasecmp(w,"AccessFileName")) {
- cfg_getword(w,l);
- strcpy(access_name,w);
- }
- else if(!strcasecmp(w,"DocumentRoot")) {
- cfg_getword(w,l);
- if(!is_directory(w)) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,
- srm_confname);
- fprintf(stderr,"%s is not a valid directory.\n",w);
- exit(1);
- }
- strcpy(document_root,w);
- }
- else if(!strcasecmp(w,"Alias")) {
- char w2[MAX_STRING_LEN];
-
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0')) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,
- srm_confname);
- fprintf(stderr,
- "Alias must be followed by a fakename, one space, then a realname.\n");
- exit(1);
- }
- add_alias(w,w2,STD_DOCUMENT);
- }
- else if(!strcasecmp(w,"AddType")) {
- char w2[MAX_STRING_LEN];
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0')) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,
- srm_confname);
- fprintf(stderr,
- "AddType must be followed by a type, one space, then a file or extension.\n");
- exit(1);
- }
- add_type(w2,w);
- }
- else if(!strcasecmp(w,"AddEncoding")) {
- char w2[MAX_STRING_LEN];
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0')) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,
- srm_confname);
- fprintf(stderr,
- "AddEncoding must be followed by a type, one space, then a file or extension.\n");
- exit(1);
- }
- add_encoding(w2,w);
- }
- else if(!strcasecmp(w,"Redirect")) {
- char w2[MAX_STRING_LEN];
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
- fprintf(stderr,"Syntax error on line %d of %s:\n",n,
- srm_confname);
- fprintf(stderr,
- "Redirect must be followed by a document, one space, then a URL.\n");
- exit(1);
- }
- add_redirect(w,w2);
- }
- }
- }
- fclose(cfg);
- }
-
-
- /* Auth Globals */
- char *auth_type;
- char *auth_name;
- char *auth_pwfile;
- char *auth_grpfile;
-
- /* Access Globals*/
- int num_sec;
- #ifndef AMIGA
- security_data sec[MAX_SECURITY];
- #else
- security_data __far sec[MAX_SECURITY];
- #endif
-
- void access_syntax_error(int n, char *err, char *file) {
- if(!file) {
- fprintf(stderr,"Syntax error on line %d of access config. file.\n",n);
- fprintf(stderr,"%s\n",err);
- exit(1);
- }
- else {
- char e[MAX_STRING_LEN];
- sprintf(e,"httpd: syntax error or override violation in access control file %s, reason: %s",file,err);
- die(SERVER_ERROR,e,stdout); /* AAAAAGH STDOUT */
- }
- }
-
- int parse_access_dir(FILE *f, int line, char or, char *dir, char *file)
- {
- char l[MAX_STRING_LEN];
- char t[MAX_STRING_LEN];
- char w[MAX_STRING_LEN];
- char w2[MAX_STRING_LEN];
- int n=line;
- register int x,i;
-
- x = num_sec;
-
- sec[x].opts=OPT_ALL;
- sec[x].override = or;
- sec[x].d = (char *)malloc((sizeof(char)) * (strlen(dir) + 2));
- strcpy_dir(sec[x].d,dir);
- sec[x].auth_type = NULL;
- sec[x].auth_name = NULL;
- sec[x].auth_pwfile = NULL;
- sec[x].auth_grpfile = NULL;
- for(i=0;i<METHODS;i++) {
- sec[x].order[i] = DENY_THEN_ALLOW;
- sec[x].num_allow[i]=0;
- sec[x].num_deny[i]=0;
- sec[x].num_auth[i] = 0;
- }
-
- while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
- ++n;
- if((l[0] == '#') || (!l[0])) continue;
- cfg_getword(w,l);
-
- if(!strcasecmp(w,"AllowOverride")) {
- if(file)
- access_syntax_error(n,"override violation",file);
- sec[x].override = OR_NONE;
- while(l[0]) {
- cfg_getword(w,l);
- if(!strcasecmp(w,"Limit"))
- sec[x].override |= OR_LIMIT;
- else if(!strcasecmp(w,"Options"))
- sec[x].override |= OR_OPTIONS;
- else if(!strcasecmp(w,"FileInfo"))
- sec[x].override |= OR_FILEINFO;
- else if(!strcasecmp(w,"AuthConfig"))
- sec[x].override |= OR_AUTHCFG;
- else if(!strcasecmp(w,"None"))
- sec[x].override = OR_NONE;
- else if(!strcasecmp(w,"All"))
- sec[x].override = OR_ALL;
- else {
- access_syntax_error(n,
- "Unknown keyword in AllowOverride directive.",file);
- }
- }
- }
- else if(!strcasecmp(w,"Options")) {
- if(!(or & OR_OPTIONS))
- access_syntax_error(n,"override violation",file);
- sec[x].opts = OPT_NONE;
- while(l[0]) {
- cfg_getword(w,l);
- if(!strcasecmp(w,"Indexes"))
- sec[x].opts |= OPT_INDEXES;
- else if(!strcasecmp(w,"Includes"))
- sec[x].opts |= OPT_INCLUDES;
- else if(!strcasecmp(w,"FollowSymLinks"))
- sec[x].opts |= OPT_SYM_LINKS;
- else if(!strcasecmp(w,"None"))
- sec[x].opts = OPT_NONE;
- else if(!strcasecmp(w,"All"))
- sec[x].opts = OPT_ALL;
- else {
- access_syntax_error(n,
- "Unknown keyword in Options directive.",file);
- }
- }
- }
- else if(!strcasecmp(w,"AuthName")) {
- if(!(or & OR_AUTHCFG))
- access_syntax_error(n,"override violation",file);
- if(sec[x].auth_name)
- free(sec[x].auth_name);
- sec[x].auth_name = strdup(l);
- }
- else if(!strcasecmp(w,"AuthType")) {
- if(!(or & OR_AUTHCFG))
- access_syntax_error(n,"override violation",file);
- cfg_getword(w,l);
- if(sec[x].auth_type)
- free(sec[x].auth_type);
- sec[x].auth_type = strdup(w);
- }
- else if(!strcasecmp(w,"AuthUserFile")) {
- if(!(or & OR_AUTHCFG))
- access_syntax_error(n,"override violation",file);
- cfg_getword(w,l);
- if(sec[x].auth_pwfile)
- free(sec[x].auth_pwfile);
- sec[x].auth_pwfile = strdup(w);
- }
- else if(!strcasecmp(w,"AuthGroupFile")) {
- if(!(or & OR_AUTHCFG))
- access_syntax_error(n,"override violation",file);
- cfg_getword(w,l);
- if(sec[x].auth_grpfile)
- free(sec[x].auth_grpfile);
- sec[x].auth_grpfile = strdup(w);
- }
- else if(!strcasecmp(w,"AddType")) {
- if(!(or & OR_FILEINFO))
- access_syntax_error(n,"override violation",file);
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0')) {
- access_syntax_error(n,
- "AddType must be followed by a type, one space, then a file or extension.",
- file);
- }
- add_type(w2,w);
- }
- else if(!strcasecmp(w,"AddEncoding")) {
- if(!(or & OR_FILEINFO))
- access_syntax_error(n,"override violation",file);
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0')) {
- access_syntax_error(n,
- "AddEncoding must be followed by a type, one space, then a file or extension.",
- file);
- }
- add_encoding(w2,w);
- }
- else if(!strcasecmp(w,"Redirect")) {
- if(!(or & OR_FILEINFO))
- access_syntax_error(n,"override violation",file);
- cfg_getword(w,l);
- cfg_getword(w2,l);
- if((w[0] == '\0') || (w2[0] == '\0') || (!is_url(w2))) {
- access_syntax_error(n,
- "Redirect must be followed by a document, one space, then a URL.",file);
- }
- if(!file)
- add_redirect(w,w2);
- else
- access_syntax_error(n,
- "Redirect no longer supported from .htaccess files.",file);
- }
- else if(!strcasecmp(w,"<Limit")) {
- int m[METHODS];
-
- if(!(or & OR_LIMIT))
- access_syntax_error(n,"override violation",file);
- for(i=0;i<METHODS;i++) m[i] = 0;
- getword(w2,l,'>');
- while(w2[0]) {
- cfg_getword(w,w2);
- if(!strcasecmp(w,"GET")) m[M_GET]=1;
- else if(!strcasecmp(w,"PUT")) m[M_PUT]=1;
- else if(!strcasecmp(w,"POST")) m[M_POST]=1;
- }
- while(1) {
- if(cfg_getline(l,MAX_STRING_LEN,f))
- access_syntax_error(n,"Limit missing /Limit",file);
- n++;
- if((l[0] == '#') || (!l[0])) continue;
-
- if(!strcasecmp(l,"</Limit>"))
- break;
- cfg_getword(w,l);
- if(!strcasecmp(w,"order")) {
- if(!strcasecmp(l,"allow,deny")) {
- for(i=0;i<METHODS;i++)
- if(m[i])
- sec[x].order[i] = ALLOW_THEN_DENY;
- }
- else if(!strcasecmp(l,"deny,allow")) {
- for(i=0;i<METHODS;i++)
- if(m[i])
- sec[x].order[i] = DENY_THEN_ALLOW;
- }
- else
- access_syntax_error(n,"Unknown order.",file);
- }
- else if((!strcasecmp(w,"allow"))) {
- cfg_getword(w,l);
- if(strcmp(w,"from"))
- access_syntax_error(n,
- "allow must be followed by from.",
- file);
- while(1) {
- cfg_getword(w,l);
- if(!w[0]) break;
- for(i=0;i<METHODS;i++)
- if(m[i]) {
- int q=sec[x].num_allow[i]++;
- sec[x].allow[i][q] = strdup(w);
- }
- }
- }
- else if(!strcasecmp(w,"require")) {
- for(i=0;i<METHODS;i++)
- if(m[i]) {
- int q=sec[x].num_auth[i]++;
- sec[x].auth[i][q] = strdup(l);
- }
- }
- else if((!strcasecmp(w,"deny"))) {
- cfg_getword(w,l);
- if(strcmp(w,"from"))
- access_syntax_error(n,
- "deny must be followed by from.",
- file);
- while(1) {
- cfg_getword(w,l);
- if(!w[0]) break;
- for(i=0;i<METHODS;i++)
- if(m[i]) {
- int q=sec[x].num_deny[i]++;
- sec[x].deny[i][q] = strdup(w);
- }
- }
- }
- else
- access_syntax_error(n,"Unknown keyword in Limit region.",
- file);
- }
- }
- else if(!strcasecmp(w,"</Directory>"))
- break;
- else {
- char errstr[MAX_STRING_LEN];
- sprintf(errstr,"Unknown method %s",w);
- access_syntax_error(n,errstr,file);
- return;
- }
- }
- ++num_sec;
- return n;
- }
-
-
- void parse_htaccess(char *path, char override) {
- FILE *f;
- char t[MAX_STRING_LEN];
- char d[MAX_STRING_LEN];
- int x;
-
- strcpy(d,path);
- make_full_path(d,access_name,t);
-
- if((f=fopen(t,"r"))) {
- parse_access_dir(f,-1,override,d,t);
- fclose(f);
- }
- }
-
-
- void process_access_config() {
- FILE *f;
- char l[MAX_STRING_LEN];
- char w[MAX_STRING_LEN];
- int n;
-
- num_sec = 0;n=0;
- if(!(f=fopen(access_confname,"r"))) {
- fprintf(stderr,"httpd: could not open access configuration file %s.\n",
- access_confname);
- perror("fopen");
- exit(1);
- }
- while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
- ++n;
- if((l[0] == '#') || (!l[0])) continue;
- cfg_getword(w,l);
- if(strcasecmp(w,"<Directory")) {
- fprintf(stderr,
- "Syntax error on line %d of access config. file.\n",n);
- fprintf(stderr,"Unknown directive %s.\n",w);
- exit(1);
- }
- getword(w,l,'>');
- n=parse_access_dir(f,n,OR_ALL,w,NULL);
- }
- fclose(f);
- }
-
- int get_pw(char *user, char *pw) {
- FILE *f;
- char errstr[MAX_STRING_LEN];
- char l[MAX_STRING_LEN];
- char w[MAX_STRING_LEN];
-
- if(!(f=fopen(auth_pwfile,"r"))) {
- sprintf(errstr,"Could not open user file %s",auth_pwfile);
- die(SERVER_ERROR,errstr,stdout); /* AAAAAAAAGH stdout */
- }
- while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
- if((l[0] == '#') || (!l[0])) continue;
- getword(w,l,':');
-
- if(!strcmp(user,w)) {
- strcpy(pw,l);
- fclose(f);
- return 1;
- }
- }
- fclose(f);
- return 0;
- }
-
-
- struct ge {
- char *name;
- char *members;
- struct ge *next;
- };
-
- static struct ge *grps;
-
- int init_group(char *grpfile) {
- FILE *f;
- struct ge *p;
- char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
-
- if(!(f=fopen(grpfile,"r")))
- return 0;
-
- grps = NULL;
- while(!(cfg_getline(l,MAX_STRING_LEN,f))) {
- if((l[0] == '#') || (!l[0])) continue;
- getword(w,l,':');
- p = (struct ge *) malloc (sizeof(struct ge));
- p->name = strdup(w);
- p->members = strdup(l);
- p->next = grps;
- grps = p;
- }
- fclose(f);
- return 1;
- }
-
- int in_group(char *user, char *group) {
- struct ge *p = grps;
- char l[MAX_STRING_LEN],w[MAX_STRING_LEN];
-
- while(p) {
- if(!strcmp(p->name,group)) {
- strcpy(l,p->members);
- while(l[0]) {
- getword(w,l,' ');
- if(!strcmp(w,user))
- return 1;
- }
- }
- p=p->next;
- }
- return 0;
- }
-
- void kill_group() {
- struct ge *p = grps, *q;
-
- while(p) {
- free(p->name);
- free(p->members);
- q=p;
- p=p->next;
- free(q);
- }
- }
-
- void read_config()
- {
- reset_aliases();
- process_server_config();
- init_mime();
- process_resource_config();
- process_access_config();
- }
-